home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************/
- /** Program: Stow Version: 0.7ß **/
- /** Date: November 1993 **/
- /** Author: Leonard D Atkinson II **/
- /** **/
- /** Purpose: Stow examines a given pathname for files and then copies **/
- /** those files to a device, volume by volume, with the lease **/
- /** ammount of waste of space. It optionally outputs a list of **/
- /** what volumes hold what files. **/
- /** **/
- /** Requires: LIST, COPY, FORMAT commands somewhere in the path. **/
- /** **/
- /** This source copyright 1993 by Leonard D Atkinson II **/
- /*****************************************************************************/
-
-
- /****************************/
- /* INCLUDES */
- /****************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h> /*so we can make unique filename*/
- #include <libraries/dos.h> /*for the checking disk space*/
- #include <exec/memory.h> /*for AllocMem()*/
- #include "ansi.h" /*My own ansi macros*/
-
- /****************************/
- /* Data Types */
- /****************************/
- struct my_file_node { /*For putting files into linked list*/
- char filename[40];
- long filesize;
- struct my_file_node *next;
- };
-
- FILE *fp; /*Generic file point for reading temp file*/
- /*and writing to the output file */
- /****************************/
- /* functions */
- /****************************/
- long check_free_space(char *); /*Returns the free space on the given volume*/
- void bad_format(); /*sends user format and exits*/
- void set_num(); /*changes the integer into ABC form*/
- void set_format();/*sets first arg to string to append to format call*/
- void my_system();/*execute system call with error checking*/
- void verify_file();/*checks given filesize to copied filesize*/
- void cat_files();/*tack arg2 onto arg3*/
-
- /*****************************************************************************/
- /* Main */
- /*****************************************************************************/
- main(int argc, char *argv[]) {
-
- /****************************/
- /* Variables */
- /****************************/
- char filename[40], /*global filename, for reading into*/
- dos_input[80], /*Working strings*/
- temp_file_name[80];
- long filesize = 0; /*global filesize, for reading into*/
- long total = 0; /*total bytes tally*/
-
- struct my_file_node *head, /*Pointers to linked list*/
- *temp,
- *temp2;
-
- char keep_going; /*boolean for the main loop*/
-
- int volume_num = 0; /*counter of number of volumes used*/
- int count,i; /*generic count variable*/
- char list_output[40] = "";/*name of list of files copied.*/
- char input_dir[40] = "";/*input directory to be copied from*/
-
- int assumed_size = 842*1024;
- int current_disk;
- int check_size;
- char output_device[40] = "";
- char output_script[40] = "";
- char fixed_size = 0;
- int max_waste = 20000;
- char use_max_waste = 0;
- char archive_name[40] = "STOW_";
- char format_options[40] = "";
- char verify_copies = 0;
- char quiet_output = 0;
- char list_sort = 1;
- char current_diskname[4] = "";
-
- /***********************************************************/
- /* Parse command line arguments */
- /***********************************************************/
- for(count = 1; count < argc; count++) {
- if(argv[count][0] == '-') {
- switch(argv[count][1]) {
- case 'i':/*input directory*/
- case 'I':
- strcpy(input_dir,&argv[count][2]);
- break;
- case 'o':
- case 'O':
- strcpy(list_output,&argv[count][2]);
- break;
- case 'a':
- case 'A':
- if(strlen(argv[count]) > 2){
- assumed_size = atoi(&argv[count][2]);
- assumed_size *= 1024;
- }
- fixed_size = 1;
- current_disk = assumed_size;
- break;
- case 'd':
- case 'D':
- strcpy(output_device,&argv[count][2]);
- break;
- case 'm':
- case 'M':
- use_max_waste = 1;
- if(strlen(argv[count]) > 2){
- max_waste = atoi(&argv[count][2]);
- max_waste *= 1024;
- }
- break;
- case 's':
- case 'S':
- strcpy(output_script,&argv[count][2]);
- break;
- case 'n':
- case 'N':
- strncpy(archive_name,&argv[count][2],16);
- strcat(archive_name,"_");
- /*turn all non-printables into underscores*/
- for(i = 0; i<strlen(archive_name); i++)
- if(isspace(archive_name[i])) archive_name[i] = '_';
- break;
- case 'f':
- case 'F':
- /*if options are provided, do it, else just put*/
- /*a space in there for signaling purposes*/
- if(argv[count][2] != NULL) {
- set_format(format_options,&(argv[count][2]));
- }
- else {
- strcpy(format_options," ");
- }
- break;
- case 'v':
- case 'V':
- verify_copies = 1;
- break;
- case 'q':
- case 'Q':
- quiet_output = 1;
- break;
- case 'l':
- case 'L':
- list_sort = 0;
- break;
- default:
- bad_format();
- }
- }
- else bad_format();
- }
-
- if((strlen(output_device) == 0) || (strlen(input_dir) == 0)) bad_format();
-
- if((strlen(output_script) > 0) && (fixed_size != 1)) {
- printf("Output scripts require an assumed size.\n");
- printf("Auto-enabling an assumed size of %d.\n",assumed_size);
- fixed_size = 1;
- current_disk = assumed_size;
- }
-
- if(quiet_output != 1) printf("Assembling the list of files to be stowed.\n");
-
- /***********************************************************/
- /*Call the LIST command to make a list of all the files */
- /*name the file with current time afterwards to avoid */
- /*two versions of the program from clobbering each other's */
- /*temp files. */
- /***********************************************************/
- sprintf(temp_file_name, "t:stow%d", (unsigned int)time(NULL));
- sprintf(dos_input, "list %s %s >%s", input_dir, "lformat \"%S %L\"", temp_file_name );
- my_system(dos_input,"Can't create file list in temp!");
-
- fp = fopen(temp_file_name,"r"); /*open the file just created*/
- if(fp == NULL) {
- ChangeColors(YELLOW,BLACK);
- printf("For some reason the temp file can't be opened!\n");
- ChangeColors(RED,BLACK);
- exit(1);
- }
-
- /*Make a head node*/
- head = (struct my_file_node *) AllocMem( sizeof(struct my_file_node),
- MEMF_PUBLIC | MEMF_CLEAR );
- if(head == NULL) {
- ChangeColors(YELLOW,BLACK);
- printf("Couldn't allocate memory!\n");
- ChangeColors(RED,BLACK);
- exit(1);
- }
- head->next = NULL;
-
- /****************************/
- /* Build Linked List */
- /****************************/
- while(fscanf(fp, "%s %d",filename,&filesize) != EOF) {/*while more*/
- if((filesize > 0) && (strlen(filename)>0)) {
- /*only bother making nodes for non-empty files*/
- /*with valid names */
- total += filesize;
- /*make a new node*/
- temp = (struct my_file_node *)
- AllocMem( sizeof(struct my_file_node),
- MEMF_PUBLIC | MEMF_CLEAR );
- if(temp == NULL) {
- ChangeColors(YELLOW,BLACK);
- printf("Couldn't allocate memory!\n");
- ChangeColors(RED,BLACK);
- exit(1);
- }
- strcpy(temp->filename, filename);/*fill with information*/
- temp->filesize = filesize;
-
- temp2 = head;/*Find the right place to insert new node*/
-
- if(list_sort == 1) {
- while((temp2->next != NULL) &&
- (((temp2->next)->filesize) > (temp->filesize)))
- temp2 = temp2->next;
- }
- else {
- /*just add to end of list now*/
- while(temp2->next != NULL) temp2 = temp2->next;
- }
-
- /*Insert Node*/
- if(temp2->next == NULL) {
- temp2->next = temp;
- temp->next = NULL;
- }
- else {
- temp->next = temp2->next;
- temp2->next = temp;
- }
- }
- }
- fclose(fp); /*close temp file*/
- if(DeleteFile(temp_file_name) == TRUE) { /*delete temp file*/
- ChangeColors(YELLOW,BLACK);
- printf("For some reason the temp file can't be deleted!\n");
- ChangeColors(RED,BLACK);
- exit(1);
- }
-
- if(strlen(list_output) > 0) { /*if requested, open output file*/
- fp = fopen(list_output,"w");
- if(fp == NULL) {
- ChangeColors(YELLOW,BLACK);
- printf("Error--Cannot open file %s for output.\n",list_output);
- ChangeColors(RED,BLACK);
- exit(1);
- }
- fprintf(fp,"!!! Files Stowed !!!\n");
- fclose(fp);
- }
- if(strlen(output_script) > 0) { /*if requested, open output script*/
- fp = fopen(output_script,"w");
- if(fp == NULL) {
- ChangeColors(YELLOW,BLACK);
- printf("Error--Cannot open file %s for output.\n",output_script);
- ChangeColors(RED,BLACK);
- exit(1);
- }
- fprintf(fp,"echo Stowing %s from script\n",input_dir);
- fclose(fp);
- }
-
- /***************************************************************/
- /*if the input directory doesn't end in / or : then assume it's*/
- /*a directory and put the / in for later catenation. */
- /***************************************************************/
- if((input_dir[strlen(input_dir) - 1] != '/') &&
- (input_dir[strlen(input_dir) - 1] != ':'))
- strcat(input_dir, "/");
-
- if(quiet_output != 1) {
- printf("%d total bytes to be packed.\n",total);
- printf("This will take about %d FFS floppies.\n",(total/890000)+1);
- }
-
- /****************************/
- /* Main Loop */
- /****************************/
- do {
- set_num(current_diskname,volume_num);/*make new disk name*/
- if(strlen(temp_file_name) != 0) { /*if requested, open output file*/
- fp = fopen(temp_file_name,"a");
- if(fp == NULL) {
- ChangeColors(YELLOW,BLACK);
- printf("Error--Cannot open file %s for output.\n",temp_file_name);
- ChangeColors(RED,BLACK);
- exit(1);
- }
- fprintf(fp, "ask \"next disk\"\n");
- fclose(fp);
- }
-
- if(strlen(format_options) != 0) {
- sprintf(dos_input,"FORMAT DRIVE %s NAME %s%s %s",
- output_device,archive_name,current_diskname, format_options);
- if(strlen(output_script) != 0) { /*if requested, open output file*/
- fp = fopen(output_script,"a");
- if(fp == NULL) {
- ChangeColors(YELLOW,BLACK);
- printf("Error--Cannot open file %s for output.\n",temp_file_name);
- ChangeColors(RED,BLACK);
- exit(1);
- }
- fprintf(fp, "%s\n",dos_input);
- fclose(fp);
- }
- else {
- my_system(dos_input,"Can't format disk!\n");
- }
- }
-
- keep_going = FALSE;
- temp = head->next;
- temp2 = head;
- while(temp != NULL) {
- /*Scan the whole list*/
- if(fixed_size == 1){
- check_size = current_disk;
- }
- else {
- check_size = (check_free_space(output_device) - 3076);
- }
- if(temp->filesize < check_size) {
- /**************************************************/
- /*if the file will fit on the volume, put it there*/
- /*3K may be a bit large, but 1K is too small */
- /*Better safe than sorry, I guess */
- /**************************************************/
-
- /*Inform user what's going on*/
- if(quiet_output != 1) {
- printf("%c %c",13,13);
- printf("Copying %s",temp->filename);
- }
-
- /*assemble dos call to COPY*/
- sprintf(dos_input, "copy %s%s %s",input_dir,temp->filename,output_device);
- if(fixed_size == 1) current_disk -= temp->filesize;
- if(strlen(output_script) > 0) { /*if requested, open output file*/
- fp = fopen(output_script,"a");
- if(fp == NULL) {
- ChangeColors(YELLOW,BLACK);
- printf("Error--Cannot open file %s for output.\n",list_output);
- ChangeColors(RED,BLACK);
- exit(1);
- }
- fprintf(fp,"%s\n",dos_input);
- fclose(fp);
- }
- else {
- my_system(dos_input,"Copy Failed!\n");
- }
- if(verify_copies == 1) {
- sprintf(filename,"%s%s",input_dir,temp->filename);
- verify_file(filename,temp->filesize);
- }
- /*Add filename to output file*/
- if(strlen(list_output) > 0) { /*if requested, open output file*/
- fp = fopen(list_output,"a");
- if(fp == NULL) {
- ChangeColors(YELLOW,BLACK);
- printf("Error--Cannot open file %s for output.\n",list_output);
- ChangeColors(RED,BLACK);
- exit(1);
- }
- fprintf(fp,"%-32.32s %6.6d %s%s\n",temp->filename,temp->filesize,archive_name,current_diskname);
-
- fclose(fp);
- }
- temp2->next = temp->next;/*remove node from list*/
- FreeMem(temp, sizeof(struct my_file_node));/*delete node*/
- temp = temp2->next; /*move temp to next in list*/
- }
-
- else {
- /*if this file won't fit, try next smaller one*/
- temp2 = temp;
- temp = temp->next;
- }
- }/*end of while list-pointer-not-null loop*/
- if(quiet_output != 1) putchar(13);
-
- if(((use_max_waste == 1) && (current_disk < max_waste)) || (use_max_waste == 0)) {
- if(strlen(output_script) > 0) {
- cat_files(output_script,temp_file_name);
- fp = fopen(output_script,"a");
- if(fp == NULL) {
- ChangeColors(YELLOW,BLACK);
- printf("Error--Cannot open file %s for output.\n",list_output);
- ChangeColors(RED,BLACK);
- exit(1);
- }
- fprintf(fp,"echo disk finished\necho %d bytes free on disk\n",current_disk);
- fclose(fp);
- }
- else {
- printf("Remove the volume in %s and put in another.\n",output_device);
- printf("Press RETURN");
- getchar();
- }
- if(fixed_size == 1) current_disk = assumed_size;
- if(head->next != NULL) keep_going = TRUE;
- }
- volume_num++;/*advance to next volume number*/
- } while(keep_going);
- if(quiet_output != 1) printf("Finished \n");
- }/*end of main*/
-
-
- /******************************************************************************/
- /**check_free_space() **/
- /**Takes the name of a device and returns the bytes free **/
- /******************************************************************************/
- long check_free_space(char *checked_device) {
-
- /*************************/
- /* Variables */
- /*************************/
- struct FileLock *lock;
- struct InfoData *info_ptr;
- long return_value;
-
- /***********************************/
- /*Get a new InfoData structure */
- /*AllocMem assures a 4 byte boundry*/
- /***********************************/
- info_ptr = (struct InfoData *) AllocMem( sizeof( struct InfoData ),
- MEMF_PUBLIC | MEMF_CLEAR );
- if( info_ptr == NULL ) {
- ChangeColors(YELLOW,BLACK);
- printf("Couldn't allocate memory!\n");
- ChangeColors(RED,BLACK);
- exit(1);
- }
-
- /*get a file lock*/
- lock = (struct FileLock *) Lock( checked_device, SHARED_LOCK );
- if( lock == NULL ) {
- ChangeColors(YELLOW,BLACK);
- printf("Could not lock your desination device!\n");
- ChangeColors(RED,BLACK);
- FreeMem( info_ptr, sizeof( struct InfoData ) );
- exit(1);
- }
- if( Info( lock, info_ptr ) == NULL ) {
- ChangeColors(YELLOW,BLACK);
- printf("Could not examine your destination device!\n");
- ChangeColors(RED,BLACK);
- FreeMem( info_ptr, sizeof( struct InfoData ) );
- UnLock( lock );
- exit(1);
- }
-
- /*Set return value*/
- return_value = (info_ptr->id_NumBlocks - info_ptr->id_NumBlocksUsed)
- * info_ptr->id_BytesPerBlock;
-
- /*Free up the file and memory*/
- UnLock( lock );
- FreeMem( info_ptr, sizeof( struct InfoData ) );
-
- return(return_value);
- }/*end of check_free_space() */
-
- /******************************************************************************/
- /** bad_format **/
- /** instructs user that a bad format of options was given **/
- /******************************************************************************/
- void bad_format(){
- printf("Usage: stow <-command> <-command> ... <-command>\n\n");
- printf("A[#] Assume disk size I<directory> Directory to copy files from\n");
- printf("O<filename> Output list of files M[max waste] Set 'max waste'\n");
- printf("S<filename> Make script file D<device> Output device copied to\n");
- printf("N<name> Name the archive Q Be quiet\n");
- printf("F<options> Format disks V Verify all copies made\n");
- printf("L Alternate list pack\n");
- exit(1);
- }
-
-
- /******************************************************************************/
- /** set_num **/
- /** converts int to letter form for naming disks **/
- /******************************************************************************/
- void set_num(char *output, int num) {
-
- output[0] = 'A' + (num/(26*26));
- num -= ((num/(26*26)) * (26*26));
- output[1] = 'A' + (num/(26));
- num -= ((num/(26)) * 26);
- output[2] = 'A' + num;
-
- return;
- }
-
- /******************************************************************************/
- /** set_format **/
- /** parses the options to the format command **/
- /******************************************************************************/
- void set_format(char *out, char *in) {
-
- int count = 0;
-
- while(in[count] != NULL) {
- switch(in[count++]) {
- case 'Q':
- case 'q':
- strcat(out,"QUICK ");
- break;
- case 'F':
- case 'f':
- strcat(out,"FFS ");
- break;
- case 'N':
- case 'n':
- strcat(out,"NOICONS ");
- break;
- default:
- break;
- }
- }
- return;
- }
-
- /******************************************************************************/
- /** my_system **/
- /** Gets rid of a bunch of repetitive calls to system() **/
- /******************************************************************************/
- void my_system(char *sys_call, char *error_string) {
-
- if(system(sys_call) != 0) {
- ChangeColors(YELLOW,BLACK);
- printf("%s\n",error_string);
- ChangeColors(RED,BLACK);
- exit(1);
- }
- return;
- }
-
- /******************************************************************************/
- /** Verify_File() **/
- /** Checks actual filesize verses the original **/
- /******************************************************************************/
- void verify_file(char *checked_file, int check_size) {
- /*************************/
- /* Variables */
- /*************************/
- struct FileLock *lock;
- struct FileInfoBlock *fib_ptr;
-
- /***********************************/
- /*Get a new FileInfoBlock structure*/
- /*AllocMem assures a 4 byte boundry*/
- /***********************************/
- fib_ptr = (struct FileInfoBlock *)
- AllocMem( sizeof( struct FileInfoBlock ),
- MEMF_PUBLIC | MEMF_CLEAR );
- /* Check if we have allocated the memory successfully: */
- if( fib_ptr == NULL ) {
- ChangeColors(YELLOW,BLACK);
- printf("Couldn't allocate memory!\n");
- ChangeColors(RED,BLACK);
- exit(1);
- }
-
- /*get a file lock*/
- lock = (struct FileLock *) Lock( checked_file, SHARED_LOCK );
- if( lock == NULL ) {
- ChangeColors(YELLOW,BLACK);
- printf("Could not lock %s!\n",checked_file);
- ChangeColors(RED,BLACK);
- FreeMem( fib_ptr, sizeof( struct FileInfoBlock ) );
- exit(1);
- }
-
- if( Examine( lock, fib_ptr ) == NULL ) {
- ChangeColors(YELLOW,BLACK);
- printf("Could not examine %s!\n",checked_file);
- ChangeColors(RED,BLACK);
- FreeMem( fib_ptr, sizeof( struct FileInfoBlock ) );
- UnLock( lock );
- exit(1);
- }
-
- /*Set return value*/
- if(fib_ptr->fib_Size != check_size) {
- ChangeColors(YELLOW,BLACK);
- printf("%s did not verify!\n",checked_file);
- ChangeColors(RED,BLACK);
- FreeMem( fib_ptr, sizeof( struct FileInfoBlock ) );
- UnLock( lock );
- exit(1);
- }
-
- /*Free up the file and memory*/
- UnLock( lock );
- FreeMem( fib_ptr, sizeof( struct FileInfoBlock ) );
-
- return;
- }/*end of verify_file() */
-
- /******************************************************************************/
- /**cat_files() **/
- /**stick the second file onto the end of the first and delete it **/
- /******************************************************************************/
- void cat_files(char *start_file, char *end_file) {
-
- FILE *fp1;
- FILE *fp2;
- char c;
-
- fp1 = fopen(start_file,"a");
- if(fp1 == NULL) {
- ChangeColors(YELLOW,BLACK);
- printf("Error--Cannot open file %s for output.\n",start_file);
- ChangeColors(RED,BLACK);
- exit(1);
- }
- fp2 = fopen(end_file,"r");
- if(fp2 == NULL) {
- ChangeColors(YELLOW,BLACK);
- printf("Error--Cannot open file %s for input.\n",end_file);
- ChangeColors(RED,BLACK);
- exit(1);
- }
- c = fgetc(fp2);
- while(c != EOF) {
- fputc(c, fp1);
- c = fgetc(fp2);
- }
- fclose(fp1);
- fclose(fp2);
- if(DeleteFile(end_file) == TRUE) { /*delete temp file*/
- ChangeColors(YELLOW,BLACK);
- printf("For some reason the temp file can't be deleted!\n");
- ChangeColors(RED,BLACK);
- exit(1);
- }
- return;
- }
-
-